package com.example.demo.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

import java.io.PrintWriter;

@Configuration
@EnableWebSecurity //启用Spring Security的Web安全支持
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    /**
     * 将用户设置到内存中
     * @param auth
     * @throws Exception
     */
    @Autowired
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
     //在内存中配置用户,配置多个用户调用'and()' 方法
        auth.inMemoryAuthentication()
                .passwordEncoder(passwordEncoder())//指定加密方式
                .withUser("admin").password(passwordEncoder().encode("123456")).roles("ADMIN")
                .and()
                .withUser("test").password(passwordEncoder().encode("123456")).roles("USER");
}

    /**
     * 登录处理
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
       //开启登录配置
        http.authorizeRequests()
                //标识访问 '/index' 这个接口，需要具备ADMIN角色
              .antMatchers("/index").hasRole("ADMIN")
                //允许匿名的url - 可理解为放行接口 - 多个接口使用，分割
              .antMatchers("/","/home").permitAll()
                // 其余所有请求都需要认证
              .anyRequest().authenticated()
              .and()
                // 设置登录认证页面
              .formLogin().loginPage("/login")
                // 登录成功后的处理接口 -方式
              .loginProcessingUrl("/home")
                // 自定义登录用户名和密码属性名，默认为username 和 password
              .usernameParameter("username")
              .passwordParameter("pasword")
                // 登录成功后的处理器 -方式
          /*    .successHandler((req, resp, authentication) ->{
                  resp.setContentType("application/json;charset=utf-8");
                  PrintWriter out = resp.getWriter();
                  out.write("登录成功...");
                  out.flush();
              })*/
                 //配置登录失败的回调
               .failureHandler((req, resp, exception) ->{
                   resp.setContentType("application/json;charset=utf-8");
                   PrintWriter out = resp.getWriter();
                   out.flush();
                })
                .permitAll()//和表单登录相关的接口统统都直接通过
                .and()
                .logout().logoutUrl("/logout")
                 // 配置注销成功的回调
                .logoutSuccessHandler((req, resp, anthentication)->{
                    resp.setContentType("application/json'charset=urf-8");
                    PrintWriter out = resp.getWriter();
                    out.write("注销成功...");
                    out.flush();
                })
                .permitAll()
                .and()
                .httpBasic()
                .and()
                // 关闭CSRF 跨域
                .csrf().disable();

    }


    /**
     *  忽略拦截
     * @param web
     * @throws Exception
     */
    @Override
    public void configure(WebSecurity web) throws Exception {
       // 设置拦截忽略url - 会直接过滤该url - 将不会经过Spring Security 过滤器
        web.ignoring().antMatchers("/getUserInfo");
        // 设置拦截忽略文件夹， 可以对静态资源放行
        web.ignoring().antMatchers("/css/**","/js/**");
    }


    @Bean
    public PasswordEncoder passwordEncoder(){
        //BCryptPasswordEncoder: Spring Security 提供的加密工具，
        //可快速实现加密加盐
        return new BCryptPasswordEncoder();
    }



}
